﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using CommonServiceLocator.WindsorAdapter;
using ENail.ApplicationServices;
using ENail.Domain.Core;
using ENail.Domain.Data.Mapping;
using ENail.Portal.Web.Code;
using ENail.Portal.Web.Models;
using Equation.Enterprise.Framework.ApplicationServices;
using Equation.Enterprise.Framework.Domain.Data;
using Equation.Enterprise.Framework.Windsor;
using Microsoft.Practices.ServiceLocation;

namespace ENail.Portal.Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public MvcApplication()
        {
            this.BeginRequest += new EventHandler((sender, e) => { });
            this.EndRequest += new EventHandler((sender, e) => { });
        }

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

            routes.MapRoute(
                "DefaultManagement", // Route name
                "{controller}/List/{page}/{filter}", // URL with parameters
                new { controller = "Home", action = "List", page = UrlParameter.Optional, filter = UrlParameter.Optional }); // Parameter defaults

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional}); // Parameter defaults

            routes.MapRoute(
                "LogOff", // Route name
                "Login/LogOff", // URL with parameters
                new { controller = "Login", action = "LogOff"}); // Parameter defaults


            routes.MapRoute(
                "Parameter",
                "{controller}/{action}/{rId}/{aId}",
                new {controller = "Entry", action = "DelAssignment", rId = 0, aId = 0});
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            InitializeServiceLocator();
        }
        
        /// <summary>
        /// Flag to know if DbContext was initialized
        /// </summary>
        private static bool _wasDbContextInitialized = false;

        /// <summary>
        /// Used for synchronization
        /// </summary>
        private static readonly object LockObject = new Object();

        private void InitializeDbContext()
        {
            if (!_wasDbContextInitialized)
            {
                lock (LockObject)
                {
                    if (!_wasDbContextInitialized)
                    {
                        var storage = new WebContextStorage(this);
                        var mappingAssembly = typeof (EmployeeMapping).Assembly;
                        DbContextManager.Init(storage, "ENail", new Assembly[] {mappingAssembly}, true);
                        _wasDbContextInitialized = true;
                    }
                }
            }

            if (_wasDbContextInitialized)
            {
                if (DbContextManager.Current.Database.Exists())
                {
                    //DbContextManager.Current.Database.ExecuteSqlCommand("ALTER DATABASE ENail SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
                    //DbContextManager.Current.Database.Delete();
                }
                //else
                    //DbContextManager.Current.Database.Create();
            }
        }

        /// <summary>
        /// Initialize DbContext here so that DbContextManager could get the correct instance application
        /// </summary>
        public override void Init()
        {
            base.Init();
            InitializeDbContext();
        }

        /// <summary>
        /// Initialize dependency components for Application Services and Controllers
        /// </summary>
        private void InitializeServiceLocator()
        {
            IWindsorContainer container = new WindsorContainer();

            //Use our own Controller Factory
            ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
            
            //Register controllers
            container.RegisterControllers(Assembly.GetExecutingAssembly());
            //Register services for controllers
            container.RegisterFromInterface(typeof(IApplicationService), typeof(EmployeeService).Assembly);

            //Register repositories for services
            container.Register(
                Component.For(typeof (IRepository<>))
                .ImplementedBy(typeof (DbRepository<>))
                .Named("RepositoryType")
                .LifeStyle
                .Transient);
            
            ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
        }

        protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        {
            if (!this.Request.IsAuthenticated)
            {
                var listIgnores = new List<string> { ".css", ".gif", ".jpeg", ".jpg", ".js", ".png", ".ico" };
                string path = HttpContext.Current.Request.Path;
                string filepath = HttpContext.Current.Request.PhysicalPath;
                string extension = System.IO.Path.GetExtension(filepath);
                bool checkIgnore = false;

                checkIgnore = string.IsNullOrEmpty(extension) || listIgnores.Contains(extension);

                if (path != "/Login/LogOn" && !checkIgnore)
                    HttpContext.Current.Response.Redirect("~/Login/LogOn", true);
            }
        }

        protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
            {
                var identity = (FormsIdentity)HttpContext.Current.User.Identity;
                var user = (User)HttpContext.Current.Cache[identity.Name];

                if (user == null)
                {
                    user = ((ENailMembershipProvider)Membership.Provider).GetUser(HttpContext.Current.User.Identity.Name);

                    if (user != null)
                    {
                        HttpContext.Current.Cache.Add(identity.Name, user, null, Cache.NoAbsoluteExpiration,
                                                      new TimeSpan(0, 30, 0), CacheItemPriority.Default, null);
                    }
                }
                if (user != null)
                {
                    user.Identity = HttpContext.Current.User.Identity;
                    HttpContext.Current.User = user;
                }
                else
                {
                    FormsAuthentication.SignOut();
                    HttpContext.Current.Response.Redirect("/Login/LogOn", true);
                }
            }
        }
    }
}